/*****************************************************************************
Copyright 2006 Kervin L. Pierre
    EMAIL: otlkcon@adevsoft.com

This file is part of Otlkcon.

Otlkcon is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.

Otlkcon is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Lesser GNU General Public License for more details.

You should have received a copy of the Lesser GNU General Public License
along with Otlkcon; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*******************************************************************************/

#pragma once
#include "stdafx.h"
#include "O_IStream.h"
#include "otlkcon_entryid.h"
#include "otlkcon_prop2str.h"
#include "otlkcon_memory.h"
#include "otlkcon_event.h"
#include <sqlite/sqlite3.h>

#include <set>

extern DWORD  otlkcon_tlsIndex;
extern CRITICAL_SECTION otlkcon_sqlite_cs;

class otlkcon_generic_msgstore;

using namespace std;

class O_IProp : public IMAPIProp
{
public:
	MAPI_IUNKNOWN_METHODS(IMPL);
    MAPI_IMAPIPROP_METHODS(IMPL);
	/* STDMETHODIMP GetLastError(HRESULT hResult,
        ULONG ulFlags,
        LPMAPIERROR *lppMAPIError);
    STDMETHODIMP SaveChanges(ULONG ulFlags);
    STDMETHODIMP GetProps(LPSPropTagArray lpPropTagArray,
                      ULONG        ulFlags,
                      ULONG        *lpcValues,
                      LPSPropValue *lppPropArray);
    STDMETHODIMP GetPropList(ULONG ulFlags, LPSPropTagArray *lppPropTagArray);
    STDMETHODIMP OpenProperty(ULONG ulPropTag,
        LPCIID lpiid,
        ULONG ulInterfaceOptions,
        ULONG ulFlags,
        LPUNKNOWN *lppUnk);
    STDMETHODIMP SetProps(ULONG cValues, LPSPropValue lpPropArray,
                                          LPSPropProblemArray *lppProblems);
    STDMETHODIMP DeleteProps(LPSPropTagArray lpPropTagArray,
                                        LPSPropProblemArray *lppProblems);
    STDMETHODIMP CopyTo(ULONG ciidExclude,
        LPCIID rgiidExclude,
        LPSPropTagArray lpExcludeProps,
        ULONG ulUIParam,
        LPMAPIPROGRESS lpProgress,
        LPCIID lpInterface,
        LPVOID lpDestObj,
        ULONG ulFlags,
        LPSPropProblemArray *lppProblems);
    STDMETHODIMP CopyProps(LPSPropTagArray lpIncludeProps,
        ULONG ulUIParam,
        LPMAPIPROGRESS lpProgress,
        LPCIID lpInterface,
        LPVOID lpDestObj,
        ULONG ulFlags,
        LPSPropProblemArray *lppProblems);
    STDMETHODIMP GetNamesFromIDs(LPSPropTagArray *lppPropTags,
        LPGUID lpPropSetGuid,
        ULONG ulFlags,
        ULONG *lpcPropNames,
        LPMAPINAMEID **lpppPropNames);
    STDMETHODIMP GetIDsFromNames(ULONG cPropNames,
        LPMAPINAMEID *lppPropNames,
        ULONG ulFlags,
        LPSPropTagArray *lppPropTags); */

    O_IProp(void);
    ~O_IProp(void);

	static HRESULT CreateEntryID( O_ENTRYID *eid, const MAPIUID* sg, MAPIUID ig, MAPIUID tg );
    HRESULT Create( otlkcon_generic_msgstore *mstr, MAPIUID ig, MAPIUID tg );
    HRESULT Load( otlkcon_generic_msgstore *mstr, O_ENTRYID *eid );
    void Destroy();
    HRESULT Dump();

    HRESULT GetEidFromTableName( char *tbl, O_ENTRYID **eid, otlkcon_memory *mo, const MAPIUID *sg);

    static HRESULT MAPIUID2String( MAPIUID   mu, char ** str );
    static HRESULT String2MAPIUID( MAPIUID * mu, const char * str );
    static HRESULT NewMAPIUID( MAPIUID *mu );

    HRESULT NewEntryID( const GUID tg, LPENTRYID *eid );
    HRESULT NewEntryID( MAPIUID tg, LPENTRYID *eid );

    HRESULT EntryID2String( O_ENTRYID *eid, char **str );

    HRESULT ObjectExists( O_ENTRYID *eid, HRESULT * );

    HRESULT SetLastError(HRESULT errID, char *errStr);

    // data members
    int cRef;
    int tblVersion;
    long objNum;

    bool isTransacted;

    char * databaseFilename;
    char * tableName;
    char * diskTableName;
    char * className; // For Debugging purposes
    char * objName;

    //For GetLastError
    int   lastCalledFunctionID;
    char  lastCalledFunctionName[OTLKCON_GETLASTERROR_FUNCTION_NAME_SIZE+1];
    HRESULT   lastErrorMsgID;
    char  lastErrorMsg[OTLKCON_GETLASTERROR_MSG_SIZE];

	//Henry: See GetSqlObj for comments
    //otlkcon_sqlite_helper *sqlObj;
    otlkcon_memory *memObj;

    O_ENTRYID *entryID;
    CRITICAL_SECTION objectCS;

    otlkcon_generic_msgstore *msgstore;

    // This should save us from checking constantly
    // in SaveChanges()
    bool hasBeenSaved;

    long objectId;

    O_ENTRYID *parent;

    set<ULONG> deletedProperties;
    set<ULONG> computedProperties;

    // TODO:  Maybe at least attempt restricting access with 'friend' access specifier?
    STDMETHODIMP _IntSetProps(ULONG cValues, 
                               LPSPropValue lpPropArray,
                               LPSPropProblemArray *lppProblems );
    STDMETHODIMP _IntGetProps(LPSPropTagArray lpPropTagArray,
                      ULONG        ulFlags,
                      ULONG        *lpcValues,
                      LPSPropValue *lppPropArray);

	//lpPropValue should reference property with correct tag set
	STDMETHODIMP _QueryValue(sqlite3_stmt *queryStmt, LPSPropValue lpPropValue, LPVOID lpParentObject);
	
	STDMETHODIMP _BuildPropQuery(
		otlkcon_sqlite_helper * sqlObj,
		const char *			lpszTableName,
		LPSPropValue			lpPropValue,
		int						transactID,
		BOOL					isReference,
		char **			lppQueryString);
	STDMETHODIMP _BindValue(sqlite3_stmt *queryStmt, LPSPropValue lpPropValue);
		
	//That is not transacted and not synchronized function
	STDMETHODIMP _QueryOneProp(ULONG ulPropTag, LPSPropValue* lppPropValue);
	
	//That is not transacted and not synchronized function
	STDMETHODIMP _StoreOneProp(LPSPropValue lpPropValue);

	STDMETHODIMP_(otlkcon_sqlite_helper *) GetSqlObj();
    HRESULT GetTableName( MAPIUID ig, MAPIUID tg, char **tbl );
    static HRESULT GetTableName( MAPIUID ig, MAPIUID tg, char **tbl, LPALLOCATEBUFFER lb );

    HRESULT ProcessEvent( otlkcon_event_struct *ev );
};
